import math
import random

class Player:

	def __init__(self):

		"""
		Optional __init__ method is run once when your Player object is created before the
		game starts

		You can add other internal (instance) variables here at your discretion.

		You don't need to define food or reputation as instance variables, since the host
		will never use them. The host will keep track of your food and reputation for you
		as well, and return it through hunt_choices.
		"""

		self.food = 0
		self.reputation = 0
		self.round_no = 0
		self.number_of_times_hunted = 0
		self.total_chances = 0
		self.opening_player = 0
 
		self.list = []
		self.stats = [[0,0]] * 101
		self.stats_last = [[0,0]] * 101
		self.stats_last3 = [[0,0]] * 101
		self.stats_last5 = [[0,0]] * 101
		self.stats_last10 = [[0,0]] * 101
		self.stats_last15 = [[0,0]] * 101
		self.stats_last20 = [[0,0]] * 101
		self.stats_last25 = [[0,0]] * 101
		self.stats_last50 = [[0,0]] * 101

		"""list that contains the results and statistics of all in all rounds."""

		self.empty_list = []

		"""And at the end"""

		self.the_golden_number = 60.0  #golden region search
		
	# All the other functions are the same as with the non object oriented setting (but they
	# should be instance methods so don't forget to add 'self' as an extra first argument).

	def hunt_choices(self, round_number, current_food, current_reputation, m,
			player_reputations):

		round_number -= 1
		self.round_no = round_number
		self.food = current_food
		self.reputation = current_reputation
		hunt_decisions = []

		if round_number == 0:

			counter = 0
			self.opening_player = len(player_reputations)
			n_p = len(player_reputations)
			#hunt_decisions = ['s'] * n_p
			for i in range(n_p):
				hunt_decisions.append('s')
			np = n_p*self.the_golden_number/100.0
			random.seed(len(player_reputations)) #giving a random seed
			while counter <= np: #put 60% of the total as hunt randomly

				m = random.randint(0, len(player_reputations) ) #random guessing 
				m %= len(player_reputations) #just in case

				if hunt_decisions[m] == 's':
					counter += 1
					hunt_decisions[m] = 'h'

			self.empty_list = player_reputations
			hunt_hunt_decisions = np

			self.number_of_times_hunted += hunt_hunt_decisions
			self.total_chances += len(player_reputations)
			#update my own reputation calculations

			return hunt_decisions

		if self.does_reputation_change( round_number, current_food, current_reputation, m, player_reputations) == False:
			#implement the routine with no constraints on how many to hunt, thus making it an against player game
			#useful when enough number of round has passed and the game is now a player vs player game

			#player by player
			for i in range(len(player_reputations)):
				rep = player_reputations[i]
				rep_percent = int(math.floor (rep*100 + 0.5) )
				#now determine how he's been playing with you

				addOne = [0] * 10

				if self.stats_last[rep_percent][1] == 0:
					addOne[0] = 1
					stats_last[rep_percent][1] = 1

				if self.stats_last3[rep_percent][1] == 0:
					addOne[1] = 1
					stats_last3[rep_percent][1] = 1

				if self.stats_last5[rep_percent][1] == 0:
					addOne[2] = 1
					stats_last5[rep_percent][1] = 1

				if self.stats_last10[rep_percent][1] == 0:
					addOne[3] = 1
					stats_last10[rep_percent][1] = 1

				if self.stats_last15[rep_percent][1] == 0:
					addOne[4] = 1
					stats_last15[rep_percent][1] = 1

				if self.stats_last20[rep_percent][1] == 0:
					addOne[5] = 1
					stats_last20[rep_percent][1] = 1

				if self.stats_last25[rep_percent][1] == 0:
					addOne[6] = 1
					stats_last25[rep_percent][1] = 1

				if self.stats_last50[rep_percent][1] == 0:
					addOne[7] = 1
					stats_last50[rep_percent][1] = 1

				if round_number >= 100 and (len(player_reputations)*5 < self.opening_player):
					if self.stats_last3[0] == self.stats_last3[1]:
						hunt_decisions.append('h')
					else:
						prob_x = self.stats_last5[0]/stats_last5[1] * 100.0
						prob_x1 = int(math.floor(prob_x)) - 5
						rand = random.randint(0 , prob_x1)
						rand %= 100
						if rand >= prob_x1:
							hunt_decisions.append('s')
						else: hunt_decisions.append('h')

				elif round_number < 5:
					if self.stats_last[rep_percent][0] == 0:
						hunt_decisions.append('s')
					else: hunt_decisions.append('h')

				elif round_number >= 5 and round_number < 10:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0))  + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0))) / 2.0
					if hunt_prob*101 > self.total_probability_all():
						hunt_decisions.append('h')
					else: hunt_decisions.append('s')

				elif round_number >= 10 and round_number < 15:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 2 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0))) / 4.0
					if hunt_prob*101 > self.total_probability_10():
						hunt_decisions.append('h')
					else:  hunt_decisions.append('s')

				elif round_number >= 15 and round_number < 20:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 3 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 2 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0)) ) / 7.0
					if hunt_prob*101 > self.total_probability_10():
						hunt_decisions.append('h')
					else: hunt_decisions.append('s')	

				elif round_number >= 20 and round_number < 25:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 4.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 3.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 2.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0)) + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0))) / 11.0
					if hunt_prob*101 > self.total_probability_20():
						hunt_decisions.append('h')
					else: hunt_decisions.append('s')	

				elif round_number >= 25 and round_number < 50:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 5.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 4.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 3.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0))* 2.0 + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0)) + (self.stats_last25[rep_percent][0]/(self.stats_last25[rep_percent][1]*1.0)) ) / 16.0
					if hunt_prob*101 > self.total_probability_20():
						hunt_decisions.append('h')
					else: hunt_decisions.append('s')

				elif round_number >= 50:
					hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 10.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 8.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 6.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0))* 4.0 + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0)) *2.0 + (self.stats_last25[rep_percent][0]/(self.stats_last25[rep_percent][1]*1.0))*2.0 + (self.stats_last50[rep_percent][0]/(self.stats_last50[rep_percent][1]*1.0)) ) / 33.0
					if hunt_prob*101 > self.total_probability_20():
						hunt_decisions.append('h')
					else: hunt_decisions.append('s')

					#here comes statistics

				#balance addOne
				if addOne[0] == 1:
					self.stats_last[rep_percent][1] = 0

				if addOne[1] == 1:
					self.stats_last3[rep_percent][1] = 0

				if addOne[2] == 1:
					self.stats_last5[rep_percent][1] = 0

				if addOne[3] == 1:
					self.stats_last10[rep_percent][1] = 0

				if addOne[4] == 1:
					self.stats_last15[rep_percent][1] = 0

				if addOne[5] == 1:
					self.stats_last20[rep_percent][1] = 0

				if addOne[6] == 1:
					self.stats_last25[rep_percent][1] = 0

				if addOne[7] == 1:
					self.stats_last50[rep_percent][1] = 0

				if rep == 0.00:
					hunt_decisions[i] = 's'
				
			#and then
			#return hunt_decisions

		else:

			prob_list = []
			unsorted_prob_list = []
			for i in range(len(player_reputations)): #make a list of player hunt probabilities
				hunt_p = self.hunt_probability(player_reputations[i], round_number)
				prob_list.append(hunt_p)
				unsorted_prob_list.append(hunt_p)

			prob_list.sort()
			how_many_to_slack = len(player_reputations) - self.how_many_to_hunt(round_number, current_food, current_reputation, m, player_reputations)
			slack_list = []
			for x in range( min(how_many_to_slack+1, len(player_reputations) ) ): #make a list of players with whose probability i will definitely slack
				slack_list.append(prob_list[i])

			for i in range( len(player_reputations) ):

				if (unsorted_prob_list[i] in slack_list):
					hunt_decisions.append('s')

				else:
					if round_number >=20:
						total_prob = total_probability_all()
					else:
						total_prob = total_probability_20()
					rand = random.randint(0 , 101)
					rand %= 100
					if rand >= 90:
						if (unsorted_prob_list[i]*202/3.0) >= total_prob:
							hunt_decisions.append('s')

					else:
						hunt_decisions.append('h')

					if player_reputations[i] == 0.00:
						hunt_decisions[i] = 's'
					

		"""self.empty_list = player_reputations
		hunt_hunt_decisions = 0

		hunt_decisions = ['h' for x in player_reputations] # replace logic with your own"""

		for i in hunt_decisions:
			if i == 'h':
				self.number_of_times_hunted += 1

		self.total_chances += len(player_reputations)

		return hunt_decisions

	def hunt_outcomes(self, food_earnings):

		temp = []
		temp_earnings = []

		for x in food_earnings:
			if x == 1 or x == -2:
				temp_earnings.append(0)
			else:
				temp_earnings.append(1)

		for i in range(len(food_earnings)):
			temp.append( (self.empty_list[i], temp_earnings[i]) )

		#temp.sort()
		self.list.append(temp)
		self.update_stats(self.round_no)
		

	def round_end(self, award, m, number_hunters):
		pass # do nothing

	def m_prediction(self, player_reputations):		
		
		#predict if the goal is going to be fullfilled

		S = 0
		for x in player_reputations:
			S += x
		p = (m - S *len(player_reputations))/len(player_reputations) * 100
		if p <= 5: return true
		else: return false

	def how_many_to_hunt(self, round_number, current_food, current_reputation, m, player_reputations):

		p = self.the_golden_number/100.0
		the_answer = p* (len(player_reputations) + self.total_chances)
		the_answer -= self.number_of_times_hunted
		if self.does_reputation_change(round_number, current_food, current_reputation, m, player_reputations):
			if (the_answer*4.0)/3.0 > len(player_reputations):
				the_answer = len(player_reputations)*3/4
			return int(math.floor(the_answer))
		else: return min(the_answer, len(player_reputations))

	def hunt_probability(self, player_reputation, round_number):

		probability = 0
		rep_percent = int(math.floor (player_reputation*100 + 0.5))

		addOne = [0] * 10

		if self.stats_last[rep_percent][1] == 0:
			addOne[0] = 1
			stats_last[rep_percent][1] = 1

		if self.stats_last3[rep_percent][1] == 0:
			addOne[1] = 1
			stats_last3[rep_percent][1] = 1

		if self.stats_last5[rep_percent][1] == 0:
			addOne[2] = 1
			stats_last5[rep_percent][1] = 1

		if self.stats_last10[rep_percent][1] == 0:
			addOne[3] = 1
			stats_last10[rep_percent][1] = 1

		if self.stats_last15[rep_percent][1] == 0:
			addOne[4] = 1
			stats_last15[rep_percent][1] = 1

		if self.stats_last20[rep_percent][1] == 0:
			addOne[5] = 1
			stats_last20[rep_percent][1] = 1

		if self.stats_last25[rep_percent][1] == 0:
			addOne[6] = 1
			stats_last25[rep_percent][1] = 1

		if self.stats_last50[rep_percent][1] == 0:
			addOne[7] = 1
			stats_last50[rep_percent][1] = 1

		if round_number < 5:
			hunt_prob = (self.stats_last3[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0))
			#return hunt_prob

		elif round_number >= 5 and round_number < 10:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0))  + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0))) / 2.0
			#return hunt_prob

		elif round_number >= 10 and round_number < 15:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 2 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0))) / 4.0
			#return hunt_prob

		elif round_number >= 15 and round_number < 20:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 3 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 2 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0)) ) / 7.0
			#return hunt_prob	

		elif round_number >= 20 and round_number < 25:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 4.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 3.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 2.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0)) + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0))) / 11.0
			#return hunt_prob	

		elif round_number >= 25 and round_number < 50:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 5.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 4.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 3.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0))* 2.0 + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0)) + (self.stats_last25[rep_percent][0]/(self.stats_last25[rep_percent][1]*1.0)) ) / 16.0
			#return hunt_prob

		elif round_number >= 50:
			hunt_prob = ((self.stats_last[rep_percent][0]/(self.stats_last[rep_percent][1]*1.0)) * 10.0 + (self.stats_last5[rep_percent][0]/(self.stats_last5[rep_percent][1]*1.0)) * 8.0 + (self.stats_last10[rep_percent][0]/(self.stats_last10[rep_percent][1]*1.0)) * 6.0 + (self.stats_last15[rep_percent][0]/(self.stats_last15[rep_percent][1]*1.0))* 4.0 + (self.stats_last20[rep_percent][0]/(self.stats_last20[rep_percent][1]*1.0)) *2.0 + (self.stats_last25[rep_percent][0]/(self.stats_last25[rep_percent][1]*1.0))*2.0 + (self.stats_last50[rep_percent][0]/(self.stats_last50[rep_percent][1]*1.0)) ) / 33.0
			#return hunt_prob

		#balance addOne
		if addOne[0] == 1:
			self.stats_last[rep_percent][1] = 0

		if addOne[1] == 1:
			self.stats_last3[rep_percent][1] = 0

		if addOne[2] == 1:
			self.stats_last5[rep_percent][1] = 0

		if addOne[3] == 1:
			self.stats_last10[rep_percent][1] = 0

		if addOne[4] == 1:
			self.stats_last15[rep_percent][1] = 0

		if addOne[5] == 1:
			self.stats_last20[rep_percent][1] = 0

		if addOne[6] == 1:
			self.stats_last25[rep_percent][1] = 0

		if addOne[7] == 1:
			self.stats_last50[rep_percent][1] = 0

		return hunt_prob

	def does_reputation_change(self, round_number, current_food, current_reputation, m, player_reputations):

		hi_p = (self.number_of_times_hunted+ len(player_reputations)) / (self.total_chances+ len(player_reputations)) * 100
		lo_p = (self.number_of_times_hunted) / (self.total_chances + len(player_reputations)) * 100
		curr_p = current_reputation * 100

		if (hi_p - curr_p) <= 1.5: #the value 1.5 had to be changesd quite hurriedly, as the number of players seemed to be far less than expected, 118 till 14/08
 			return False

		elif (curr_p - lo_p) <= 1.5:
			return False
		elif (len(player_reputations)*5 < self.opening_player):
			return False

		else: 
			return True


	def update_stats(self, round_n):

		for (a,b) in self.list[round_n]:

			self.stats[ int(math.floor(a*100.0 + 0.5) ) ][0] += b
			self.stats[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last3[ int(math.floor(a*100.0 + 0.5)) ][1] += b
			self.stats_last3[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last5[ int(math.floor(a*100.0 + 0.5)) ][1] += b
			self.stats_last5[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last10[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last10[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last15[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last15[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last20[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last20[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last25[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last25[ int(math.floor(a*100.0 + 0.5)) ][1] += 1
			self.stats_last50[ int(math.floor(a*100.0 + 0.5)) ][0] += b
			self.stats_last50[ int(math.floor(a*100.0 + 0.5)) ][1] += 1

		#adding the score of current round to all

		if round_n >= 1 :
			for (a,b) in self.list[round_n - 1 ]:
				self.stats_last[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		if round_n >= 3 :
			for (a,b) in self.list[round_n - 3 ]:
				self.stats_last3[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last3[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		if round_n >= 5 :
			for (a,b) in self.list[round_n - 5 ]:
				self.stats_last5[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last5[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		if round_n >= 10 :
			for (a,b) in self.list[round_n - 10 ]:
				self.stats_last10[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last10[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		if round_n >= 15 :
			for (a,b) in self.list[round_n - 15 ]:
				self.stats_last15[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last15[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1
		
		if round_n >= 20 :
			for (a,b) in self.list[round_n - 20 ]:
				self.stats_last20[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last20[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1
		
		if round_n >=  25 :
			for (a,b) in self.list[round_n - 25 ]:
				self.stats_last25[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last25[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		if round_n >=  50 :
			for (a,b) in self.list[round_n - 50 ]:
				self.stats_last50[ int(math.floor(a*100.0 + 0.5)) ][0] -= b
				self.stats_last50[ int(math.floor(a*100.0 + 0.5)) ][1] -= 1

		#then stabilizing the numbers of other tables

	def total_probability_all(self):
		total = 0.0
		for i in range(101):
			if self.stats[i][1] > 0:
				total += self.stats[i][0] / (self.stats[i][1]*1.0)
		return total
	 
	def total_probability_5(self):
		total = 0.0
		for i in range(101):
			if self.stats_last5[i][1] > 0:
				total += self.stats_last5[i][0] / (self.stats_last5[i][1]*1.0)
		return total

	def total_probability_10(self):
		total = 0.0
		for i in range(101):
			if self.stats_last10[i][1] > 0:
				total += self.stats_last10[i][0] / (self.stats_last10[i][1]*1.0)
		return total
	 
	def total_probability_20(self):
		total = 0.0
		for i in range(101):
			if self.stats_last20[i][1] > 0:
				total += self.stats_last20[i][0] / (self.stats_last20[i][1]*1.0)
		return total
	 